package cn.fl.login.controller.filter;

import cmm.mid.core.framework.dto.DataResultDTO;
import cmm.mid.core.framework.page.DataResultVO;
import cmm.user.facade.system.constant.SysResUrlRConstant;
import cn.cmm.base.framework.constant.BaseConstant;
import cn.lionbridge.center.api.ILoginAuthApiService;
import cn.lionbridge.center.constant.LoginConstant;
import cn.lionbridge.center.context.CurrentThreadContext;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class UrlPowerHandlerInterceptor implements HandlerInterceptor {


    private static final Logger logger = LoggerFactory.getLogger(UrlPowerHandlerInterceptor.class);


    private ILoginAuthApiService loginAuthApiService;
    public UrlPowerHandlerInterceptor(ILoginAuthApiService loginAuthApiService){
        this.loginAuthApiService = loginAuthApiService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("UrlPowerHandlerInterceptor EXE");
        if(handler instanceof HandlerMethod) {
            try {
                List<String> redisKey = getRedisKey((HandlerMethod) handler);
                logger.info(redisKey.toString());

                if(StringUtils.isNoneBlank(CurrentThreadContext.getCurrentSQID())){
                    logger.info(CurrentThreadContext.getCurrentRoleId().toString());
                    DataResultDTO dataResultDTO = loginAuthApiService.authUrl(CurrentThreadContext.getCurrentSQID(), redisKey);
                    logger.info(dataResultDTO.getSuccess()+dataResultDTO.getInfo());
                    if (!Objects.equals(BaseConstant.IS_YESNO_YES, dataResultDTO.getSuccess())) {
                        printWriter(response, dataResultDTO.getInfo());
                        return false;
                    }
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                printWriter(response, "服务异常，请稍候。。");
                return false;
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }


    private List<String> getRedisKey(HandlerMethod handler){
        //类上注解
        List<String> clazzPathList=new ArrayList<>();
        Class clazz = handler.getMethod().getDeclaringClass();
        RequestMapping clazzRequestMappingAnnotation = (RequestMapping)clazz.getAnnotation(RequestMapping.class);
        if(!Objects.isNull(clazzRequestMappingAnnotation)){
            String[] clazzPath = clazzRequestMappingAnnotation.value();
            clazzPathList.addAll(toListPath(clazzPath));
        }
        List<String> methodPathList = new ArrayList<>();
        List<RequestMethod> requestMethodList = new ArrayList<>();
        RequestMapping  requestMappingAnnotation = handler.getMethodAnnotation(RequestMapping.class);
       if (!Objects.isNull(requestMappingAnnotation)) {
            requestMethodList.addAll(Arrays.asList(requestMappingAnnotation.method()));
            String[] path = requestMappingAnnotation.value();
            methodPathList.addAll(toListPath(path));
        }
        List<String> pathList = new ArrayList<>();
        clazzPathList.forEach(clazzPath->{
            methodPathList.forEach(methodPath->{
                pathList.add( clazzPath + methodPath);
            });
        });
        List<String> result = new ArrayList<>();
        requestMethodList.forEach(requestMethod -> {
            pathList.forEach(path->{
                result.add(String.format(SysResUrlRConstant.URL_ROLE_REDIS_KEY,requestMethod.name(),path));
            });
        });
        return  result;
    }

    private  List<String> toListPath(String... path) {
        return Arrays.stream(path).map(str -> {
            if (!str.startsWith("/")) {
                str = "/" + str;
            }
            if (str.endsWith("/")) {
                str = str.substring(0, str.length() - 1);
            }
            return str;
        }).collect(Collectors.toList());
    }

    private void printWriter(ServletResponse response, String message) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter printWriter = response.getWriter()) {
            printWriter.print(JSON.toJSONString(new DataResultVO(LoginConstant.USR_EXECUTE_ACCESS_FORBIDDEN, message)));
        }
    }
    public void setLoginAuthApiService(ILoginAuthApiService loginAuthApiService) {
        this.loginAuthApiService = loginAuthApiService;
    }
}
